#ifndef OMG_DDS_CORE_STATUS_STATE_HPP_
#define OMG_DDS_CORE_STATUS_STATE_HPP_

/* Copyright (c) 2009-2010, Real-Time Innovations, Inc.
 * Copyright (c) 2010, Object Management Group, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - Neither the names of the above copyright holders nor the names of their
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL A COPYRIGHT HOLDER OR CONTRIBUTOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */


namespace dds { namespace core { namespace status {

/* By default, there can be up to 32 unique statuses. However, a
 * DDS implementation may extend this number if necessary.
 */
#define OMG_DDS_DEFAULT_STATE_BIT_COUNT 32
#define OMG_DDS_DEFAULT_STATUS_COUNT    32

#ifndef OMG_DDS_STATE_BIT_COUNT
#define OMG_DDS_STATE_BIT_COUNT         OMG_DDS_DEFAULT_STATE_BIT_COUNT
#endif  // !defined(OMG_DDS_STATE_BIT_COUNT)
    
#ifndef OMG_DDS_STATUS_COUNT
#define OMG_DDS_STATUS_COUNT            OMG_DDS_DEFAULT_STATUS_COUNT
#endif  // !defined(OMG_DDS_STATUS_COUNT)


class SampleState : public std::bitset<OMG_DDS_STATE_BIT_COUNT> {
public:
    typedef std::bitset<OMG_DDS_STATE_BIT_COUNT> MaskType;

public:
    SampleState() : MaskType() { }
    SampleState(const SampleState& src) : MaskType(src) { }
    SampleState(const MaskType& src) : MaskType(src) { }

public:
    inline static const SampleState read() {
        return SampleState(0x0001 << 0u);
    }

    inline static const SampleState not_read() {
        return SampleState(0x0001 << 1u);
    }

    inline static const SampleState any() {
        return SampleState(~0u);
    }

private:
    SampleState(uint32_t i) : MaskType(i) { }
};


class ViewState : public std::bitset<OMG_DDS_STATE_BIT_COUNT> {
public:
    typedef std::bitset<OMG_DDS_STATE_BIT_COUNT> MaskType;

public:
    ViewState() : MaskType() { }
    ViewState(const ViewState& src) : MaskType(src) { }
    ViewState(const MaskType& src) : MaskType(src) { }

public:
    inline static const ViewState new_view() {
        return ViewState(0x0001 << 0u);
    }

    inline static const ViewState not_new_view() {
        return ViewState(0x0001 << 1u);
    }

    inline static const ViewState any() {
        return ViewState(~0u);
    }
private:
    ViewState(uint32_t m) : MaskType(m) { }

};


class InstanceState : public std::bitset<OMG_DDS_STATE_BIT_COUNT> {
public:
    typedef std::bitset<OMG_DDS_STATE_BIT_COUNT> MaskType;

public:
    InstanceState() : MaskType() { }
    InstanceState(const InstanceState& src) : MaskType(src) { }
    InstanceState(const MaskType& src) : MaskType(src) { }

public:
    inline static const InstanceState alive_kind() {
        return InstanceState(0x0001 << 0u);
    }

    inline static const InstanceState not_alive_disposed_kind() {
        return InstanceState(0x0001 << 1u);
    }

    inline static const InstanceState not_alive_no_writers_kind() {
        return InstanceState(0x0001 << 2u);
    }

    inline static const InstanceState not_alive_mask() {
        return not_alive_disposed_kind() | not_alive_no_writers_kind();
    }

    inline static const InstanceState any() {
        return InstanceState(~0u);
    }
private:
    InstanceState(uint32_t m) : MaskType(m) { }

};

class SampleRejectedState : public std::bitset<OMG_DDS_STATE_BIT_COUNT> {
public:
    typedef std::bitset<OMG_DDS_STATE_BIT_COUNT> MaskType;

public:
    SampleRejectedState() : MaskType() { }
    SampleRejectedState(const SampleRejectedState& src) : MaskType(src) { }
    SampleRejectedState(const MaskType& src) : MaskType(src) { }

public:
    inline static const SampleRejectedState not_rejected() {
        return SampleRejectedState(0u);
    }
    inline static const SampleRejectedState rejected_by_samples_limit() {
        return SampleRejectedState(0x0001 << 1u);
    }
    inline static const SampleRejectedState rejected_by_instances_limit() {
        return SampleRejectedState(0x0001 << 0u);
    }
    inline static const SampleRejectedState rejected_by_samples_per_instance_limit() {
        return SampleRejectedState(0x0001 << 2u);
    }

private:
    SampleRejectedState(uint32_t s) : MaskType(s) { }

};


// Function used to create proprietary StatusMask value by vendors.
class StatusMask;

StatusMask create_status(uint64_t);

class StatusMask : public std::bitset<OMG_DDS_STATUS_COUNT> {
public:
    typedef std::bitset<OMG_DDS_STATUS_COUNT> MaskType;

public:
    StatusMask() : MaskType() { }
    StatusMask(const StatusMask& other) : MaskType(other) { }
    StatusMask(const MaskType& mask) : MaskType(mask) { }
    ~StatusMask() { }

public:
    inline static const StatusMask all() {
        return StatusMask(~0u);
    }

    inline static const StatusMask none() {
        return StatusMask(0u);
    }

private:
    StatusMask(uint64_t mask) : MaskType(mask) { }
    friend StatusMask dds::core::status::create_status(uint64_t);
};


template <typename STATUS>
class status_traits {
    // empty
};

} } } /* namespace dds / core / status */


#define OMG_DDS_STATUS_TRAITS(STATUS, KINDBIT)      \
    namespace dds {  namespace core { namespace status { \
        template <>                     \
        class status_traits<STATUS> {   \
        public:                         \
            enum { kind = (0x0001 << KINDBIT) };\
        };                              \
    } } }


#endif /* OMG_DDS_CORE_STATUS_STATE_HPP_ */
